package cn.demo.um.support.handler.base;

import cn.demo.um.domain.UmAttrData;
import cn.demo.um.service.IUmAttrDataService;
import cn.demo.um.support.handler.MatcherContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collector;
import java.util.stream.Collectors;

@Component
@Slf4j
public class RangeBaseMatcherHandler implements IBaseMatcherHandler {

    @Autowired
    private IUmAttrDataService umAttrDataService;

    @Override
    public void handler(MatcherContext matcherContext, String attrCode, double score) {
        List<String> factors = matcherContext.getFactor(attrCode);
        Integer low = Integer.valueOf(factors.getFirst());
        Integer height = Integer.valueOf(factors.getLast());
        if (low > height) {
            Integer temp = low;
            low = height;
            height = temp;
        }
        Object[][] sorts = (Object[][]) matcherContext.getSearchAttrIndexFactory().getIndexStructure(attrCode, matcherContext.getSex());
        for (int i = ge(sorts, low); i < sorts.length; i++) {
            if ((Integer) sorts[i][0] > height) {
                break;
            }
            List<String> userIds = (List<String>) sorts[i][1];
            matcherContext.addMatchScopeAttr(userIds, score, attrCode);
        }
    }

    /**
     * 范围属性统一从数据库中查
     *
     * @param umAttrDataList
     * @param attrCode
     * @return
     */
    @Override
    public Object[][] buildInvertedIndex(List<UmAttrData> umAttrDataList, String attrCode) {
        Map<String, List<String>> collect = umAttrDataList.stream().collect(Collectors.groupingBy(UmAttrData::getAttrValue, Collectors.mapping(UmAttrData::getUserId, Collectors.toList())));
        //用数组提速，0位置存年龄的值，1位置存对应的用户id集合
        Object[][] sorts = new Object[collect.size()][2];
        Set<Map.Entry<String, List<String>>> entries = collect.entrySet();
        int i = 0;
        for (Map.Entry<String, List<String>> entry : entries) {
            sorts[i][0] = Integer.parseInt(entry.getKey());
            sorts[i][1] = entry.getValue();
            i++;
        }
        Arrays.sort(sorts, (o1, o2) -> (Integer) o1[0] - (Integer) o2[0]);
        return sorts;
    }

    /*二分查找出第一个大于等于*/
    private int ge(Object[][] sorts, Integer target) {
        int l = 0, r = sorts.length - 1;
        while (l <= r) {
            int mid = l + r >> 1;   //等价于(l+r)/2
            if ((Integer) sorts[mid][0] >= target) {
                r = mid - 1;
            } else {
                l = mid + 1;
            }
        }
//        if (l >= sorts.length) return -1;
        return l;
    }
}
